import cloneDeep from 'lodash/cloneDeep';
import React from 'react';
import PropTypes from 'prop-types';
import {FormattedMessage} from 'react-intl';

import {AppIcon} from '@folio/stripes/core';
import {
  AccordionSet,
  Button,
  Col,
  ExpandAllButton,
  expandAllFunction,
  HasCommand,
  Pane,
  PaneFooter,
  PaneHeaderIconButton,
  PaneMenu,
  Paneset,
  Row,
} from '@folio/stripes/components';
import stripesForm from '@folio/stripes/form';

import {EditBookInStorageExtInfo, EditBookInStorageInfo} from '../../components/EditSections';

import {BASE_PAHT} from '../../constants';

import css from './BookInStorageForm.css';

function validate(values, props) {
  const errors = {};

  return errors;
}

function warn(values, props) {
  const warnings = {};

  return warnings;
}

function asyncValidateField(field, value, validator) {
  return new Promise((resolve, reject) => {
    const query = `(${field}=="${value}")`;
    validator.reset();

    return validator.GET({ params: { query } }).then((BookInStorages) => {
      if (BookInStorages.length > 0) {
        const error = { [field]: <FormattedMessage id={`ui-users.errors.${field}Unavailable`} /> };
        return reject(error);
      } else {
        return resolve();
      }
    });
  });
}

function asyncValidate(values, dispatch, props, blurredField) {
  const promises = [];

  return Promise.all(promises);
}

class BookInStorageForm extends React.Component {
  static propTypes = {
    change: PropTypes.func,
    formData: PropTypes.object,
    handleSubmit: PropTypes.func.isRequired,
    location: PropTypes.object,
    history: PropTypes.object,
    match: PropTypes.object,
    pristine: PropTypes.bool,
    submitting: PropTypes.bool,
    onCancel: PropTypes.func.isRequired,
    onSubmit: PropTypes.func.isRequired,
    initialValues: PropTypes.object.isRequired,
  };

  static defaultProps = {
    pristine: false,
    submitting: false,
  };

  constructor(props) {
    super(props);

    this.state = {
      sections: {
        editInfo: true,
        extendedInfo: true,
      },
    };

    this.closeButton = React.createRef();
    this.saveButton = React.createRef();
    this.cancelButton = React.createRef();

    this.keyboardCommands = [
      {
        name: 'save',
        handler: this.handleSaveKeyCommand
      },
      {
        name: 'ignoreEnter',
        handler: this.ignoreEnterKey,
        shortcut: 'enter'
      },
      {
        name: 'cancel',
        handler: this.handleCancel,
        shortcut: 'esc'
      },
      {
        name: 'expandAllSections',
        handler: this.expandAllSections,
      },
      {
        name: 'collapseAllSections',
        handler: this.collapseAllSections,
      }
    ];
  }

  handleCancel = () => {
    const {
      match: {
        params
      },
      location: {
        search,
      },
      history
    } = this.props;

    const idParam = params.id || '';
    if (idParam) {
      // if an id param is present, it's an edit view, go back to the user detail page...
      history.push(`${BASE_PAHT}/preview/${idParam}${search}`);
    } else {
      // if no id param, it's a create form, go back to the top level search view.
      history.push(`${BASE_PAHT}/${search}`);
    }
  }

  getAddFirstMenu() {
    return (
      <PaneMenu>
        <FormattedMessage id="ui-book-in-storage.crud.closeNewBookinstorageDialog">
          {ariaLabel => (
            <PaneHeaderIconButton
              id="clickable-closenewuserdialog"
              onClick={this.handleCancel}
              ref={this.closeButton}
              aria-label={ariaLabel}
              icon="times"
            />
          )}
        </FormattedMessage>
      </PaneMenu>
    );
  }

  handleExpandAll = (sections) => {
    this.setState({ sections });
  }

  ignoreEnterKey = (e) => {
    const allowedControls = [
      this.closeButton.current,
      this.saveButton.current,
      this.cancelButton.current,
    ];

    if (!allowedControls.includes(e.target)) {
      e.preventDefault();
    }
  };

  handleSectionToggle = ({ id }) => {
    this.setState((curState) => {
      const newState = cloneDeep(curState);
      newState.sections[id] = !newState.sections[id];

      return newState;
    });
  }

  toggleAllSections = (expand) => {
    this.setState((curState) => {
      const newSections = expandAllFunction(curState.sections, expand);

      return {
        sections: newSections
      };
    });
  }

  expandAllSections = (e) => {
    e.preventDefault();
    this.toggleAllSections(true);
  }

  collapseAllSections = (e) => {
    e.preventDefault();
    this.toggleAllSections(false);
  }

  handleSaveKeyCommand = (e) => {
    e.preventDefault();
    this.executeSave();
  };

  executeSave() {
    const {
      handleSubmit,
      onSubmit,
    } = this.props;

    const submitter = handleSubmit(onSubmit);

    submitter();
  }

  getPaneFooter() {
    const {
      pristine,
      submitting,
      onCancel,
    } = this.props;

    const disabled = pristine || submitting;

    const startButton = (
      <Button
        data-test-user-form-cancel-button
        marginBottom0
        id="clickable-cancel"
        buttonStyle="default mega"
        buttonRef={this.cancelButton}
        onClick={onCancel}
      >
        取消
      </Button>
    );

    const endButton = (
      <Button
        data-test-user-form-submit-button
        marginBottom0
        id="clickable-save"
        buttonStyle="primary mega"
        type="submit"
        disabled={disabled}
        buttonRef={this.saveButton}
      >
        保存并关闭
      </Button>
    );

    return (
      <PaneFooter
        renderStart={startButton}
        renderEnd={endButton}
        className={css.paneFooterClass}
        innerClassName={css.paneFooterContentClass}
      />
    );
  }

  render() {
    const {
      initialValues,
      handleSubmit,
      formData,
      change, // from redux-form...
      onCancel,
    } = this.props;

    const { sections } = this.state;
    const firstMenu = this.getAddFirstMenu();
    const footer = this.getPaneFooter();
    const paneTitle = initialValues.id ? '编辑馆藏入库' : '新增馆藏入库';

    return (
      <HasCommand commands={this.keyboardCommands}>
        <form
          data-test-form-page
          className={css.BookInStorageFormRoot}
          id="form-bookInStorage"
          onSubmit={handleSubmit}
        >
          <Paneset>
            <Pane
              firstMenu={firstMenu}
              footer={footer}
              centerContent
              appIcon={<AppIcon app="book-in-storage" appIconKey="app" />}
              paneTitle={
                <span data-test-header-title>
                  {paneTitle}
                </span>
              }
              onClose={onCancel}
            >
              <Row end="xs">
                <Col xs>
                  <ExpandAllButton
                    accordionStatus={sections}
                    onToggle={this.handleExpandAll}
                  />
                </Col>
              </Row>
              <AccordionSet>
                <EditBookInStorageInfo
                  accordionId="editBookInStorageInfo"
                  expanded={sections.editInfo}
                  onToggle={this.handleSectionToggle}
                  initialValues={initialValues}
                />
                <EditBookInStorageExtInfo
                  accordionId="extendedInfo"
                  expanded={sections.extendedInfo}
                  onToggle={this.handleSectionToggle}
                  userId={initialValues.id}
                />
              </AccordionSet>
            </Pane>
          </Paneset>
        </form>
      </HasCommand>
    );
  }
}

export default stripesForm({
  form: 'bookInStorageForm',
  validate,
  warn,
  asyncValidate,
  navigationCheck: true,
  enableReinitialize: true,
})(BookInStorageForm);
